package top.littlejiang.onlinexam.controller;

import com.alibaba.fastjson.JSONObject;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import top.littlejiang.onlinexam.common.base.BusinessException;
import top.littlejiang.onlinexam.common.utils.*;
import top.littlejiang.onlinexam.entity.OlexamUser;
import top.littlejiang.onlinexam.service.OlexamLoginService;
import top.littlejiang.onlinexam.service.OlexamSysService;
import top.littlejiang.onlinexam.service.OlexamUserService;
import top.littlejiang.onlinexam.service.impl.OlexamLoginServiceImpl;
import top.littlejiang.onlinexam.vo.LoginVO;
import top.littlejiang.onlinexam.vo.ModifyInformationVO;
import top.littlejiang.onlinexam.vo.RegisterVO;

import java.io.UnsupportedEncodingException;
import java.util.Objects;

/**
 * @author chen
 * @Description
 * @since 2020/12/26 16:31
 */
@Controller
@RequestMapping("/login")
public class LoginController {

    @Autowired
    OlexamUserService userService;
    @Autowired
    OlexamLoginService loginService;
    @Autowired
    OlexamSysService sysService;

   /**
    * 验证用户登录操作 <br>
    * 先验证 验证码是否正确 ，正确 则进行密码验证，登录成功则返回token，并存入redis
    * @param loginVo
    * @return Result
    * @author chen
    * @since 2021/2/26 14:19
    */
    @PostMapping("/checklogin")
    @ResponseBody
    public Result checkLogin(@Validated @RequestBody LoginVO loginVo) throws UnsupportedEncodingException {

        // 判断验证码是否正确
        loginService.checkValideCode(loginVo.getValiCode(), loginVo.getCodeUuid());
        // 查询用户密码与盐值
        OlexamUser olexamUser = userService.getUserByAcct(OlexamLoginServiceImpl.LOGIN_SERVICE, loginVo.getUserAccount());
        // 验证密码是否正确
        loginService.checkPwd(olexamUser.getUserPwd(), olexamUser.getUserSalty(), loginVo.getPassWord());

        olexamUser.setRoleSign(userService.getUserById(olexamUser.getId()).getRoleSign());
        String token = JWTUtils.createToken(olexamUser);

        //  将登录信息以hash存入redis key为 前缀+用户id
        //  存入信息包含用户 id，角色，是否进入考试（是，则值为考试id），ip地址
        loginService.addLoginInfo(olexamUser);

        // 构造返回体
        JSONObject rst = new JSONObject();
        rst.put("userName",olexamUser.getUserName());
        rst.put("userId",olexamUser.getId());
        rst.put("ClientToken",token);
        return Result.ok(rst);
    }

    /**
     * 登出
     * @return
     */
    @GetMapping("/loginout")
    @ResponseBody
    public Result loginOut(){
        boolean delete = RedisUtils.delKey(RedisUtils.LOGIN_PREFIX + HttpContextUtils.getHttpServletRequest().getAttribute(JWTUtils.USER_ID_IN_TOKEN));
        return delete ? Result.ok() : Result.fail();
    }


    /**
     * 修改个人信息（密码）
     * @param vo
     * @return
     */
    @PostMapping("/modify_information")
    @ResponseBody
    @RequiresPermissions("olexam:user:modify")
    public Result modifyInformation(@Validated @RequestBody ModifyInformationVO vo){
        userService.modifyOne(vo);
        return Result.ok();
    }

    /**
     * 登录页面注册用户
     * @param registerVO
     * @return
     */
    @PostMapping("/register")
    @ResponseBody
    public Result register(@RequestBody RegisterVO registerVO){
        loginService.checkValideCode(registerVO.getValiCode(), registerVO.getCodeUuid());
        String salty = PasswordUtils.getRandomValue(PasswordUtils.DEFAULT_LENGTH);
        String userPwd = PasswordUtils.md5SaltyAndPwd(salty, registerVO.getUserPwd());
        OlexamUser userByAcct = userService.getUserByAcct(OlexamLoginServiceImpl.LOGIN_SERVICE, registerVO.getUserAccount());
        if (Objects.isNull(userByAcct)){
            throw new BusinessException("用户已存在！");
        }
        OlexamUser user = new OlexamUser();
        user.setCreateTime(DateUtils.getTime())
                .setUpdateTime(DateUtils.getTime())
                .setIsDel(0)
                .setFkClassId(registerVO.getFkClassId())
                .setUserAccount(registerVO.getUserAccount())
                .setUserName(registerVO.getUserName())
                .setUserEmail(registerVO.getUserEmail())
                .setUserSex(registerVO.getUserSex())
                .setUserPhone(registerVO.getUserPhone())
                .setUserPwd(userPwd)
                .setRoleId(0)
                .setUserSalty(salty);
        sysService.saveOneUser(user);
        return Result.ok();
    }


    /**
     * 获取验证码
     * @return
     */
    @PostMapping("/validateCode")
    @ResponseBody
    public Result getValiCode(){
        String codeUuid = IPUtils.getIpAddr(HttpContextUtils.getHttpServletRequest());
        String codeId = RedisUtils.CODE_PREFIX + codeUuid;
        String valiCode = loginService.getValiCode(codeId);
        JSONObject rst = new JSONObject();
        rst.put("codeUuid", codeUuid);
        rst.put("codeImage", valiCode);
        return Result.ok(rst);
    }

    /**
     * 未授权统一返回
     * @param message
     * @return
     * @throws UnsupportedEncodingException
     */
    @RequestMapping(path = "/unauthorized/{message}")
    @ResponseBody
    public Result unauthorized(@PathVariable String message) {
        return Result.build(Result.CODE_LOGIN,message,null);
    }

}
